module key(
input clk,
input nRST,
input keyin,
output keyout
);

	reg		[20:0]	time_cnt;			//用来计数按键延迟的定时计数器
	reg		[20:0]	time_cnt_n;			//time_cnt的下一个状态
	reg		key_in_r;			//用来接收按键信号的寄存器
	reg		key_out;				//消抖完成输出按键
	reg		key_out_n;			//key_out的下一个状态
	wire		key_press;			//检测按键有没有变化

	//设置定时器的时间为20ms,计算方法为  (20*10^3)us / (1/50)us  50MHz为开发板晶振
	parameter SET_TIME_20MS = 21'd1_000_000;	
	
	assign keyout = key_out;					//将消抖的按键值赋值给LED

	//---------------------------------------------------------------------------
	//--	逻辑功能实现	
	//---------------------------------------------------------------------------
	//时序电路，用来key_in_r寄存器赋值
	always @ (posedge clk, negedge nRST)
	begin
		if(!nRST)								//判断复位
			key_in_r <= 1'b1;				//初始化key_in_r值
		else
			key_in_r <= keyin;					//将按键的值赋值给key_in_r
	end

	assign key_press = key_in_r ^ keyin;	//检测按键有没有变化


	//时序电路，用来给time_cnt寄存器赋值
	always @ (posedge clk, negedge nRST)
	begin
		if(!nRST)								//判断复位
			time_cnt <= 21'h0;				//初始化time_cnt值
		else
			time_cnt <= time_cnt_n;			//用来给time_cnt赋值
	end

	//组合电路，实现20ms的定时计数器
	always @ (*)
	begin
		if(time_cnt == SET_TIME_20MS || key_press) //判断按键有没有变化、时间有没有到
			time_cnt_n = 21'h0;				//如果到达20ms或者按键有了变化,那么定时计数器将会被清零
		else
			time_cnt_n = time_cnt + 1'b1; //如果未到20ms或者按键没有变化,那么定时计数器将会继续累加
	end

	//时序电路，用来key_out寄存器赋值
	always @ (posedge clk, negedge nRST)
	begin
		if(!nRST)								//判断复位
			key_out <= 1'b1;					//初始化key_out值
		else
			key_out <= key_out_n;			//用来给key_out赋值
	end

	//组合电路，每20ms接收一次按键的值
	always @ (*)
	begin
		if(time_cnt == SET_TIME_20MS)		//判断20ms时间
			key_out_n = key_in_r;			//如果到达20ms,接收一次按键的值
		else
			key_out_n = key_out;				//如果未到20ms,保持原状态不变
	end


endmodule
